﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Common;
using BLL.Properties;
using System.Threading;
using System.Diagnostics;

namespace BLL
{
    public class PassportSerialPort
    {
        private SerialPort COM = null;
        private byte Pillar;
//        private PassportInfoData PInfo;
        public PassportSerialPort(byte pillar)
        {
            this.Pillar=pillar;
        }
//         public PassportSerialPort(byte pillar, PassportInfoData p)
//         {
//             this.Pillar=pillar;
//             this.PInfo=p;
//         }
//         public RS485Result SavePassport(out byte[] RxBuffer, out ushort Count)
//         {
//             Count = 0;
//             RxBuffer = null;
//             byte[] Tx;
//             byte[] RxTemp;
//             Tx = new byte[10];
//             RxTemp = new byte[500];           
//             RS485Result ret;            
//             if (!OpenSerialPort())
//                 return RS485Result.Close;           
//             ret = GetPassportState(out RxBuffer, out Count);
//             if (ret != RS485Result.OK)
//                 return ret;
//             CloseSerialPort();
//             return ret;
//         }
//         public RS485Result TakeOutPassport(out byte[] RxBuffer, out ushort Count)
//         {
//             Count = 0;
//             RxBuffer = null;
//             byte[] Tx;
//             byte[] RxTemp;
//             Tx = new byte[10];
//             RxTemp = new byte[500];
//             Boolean bForwardMoving;
//             byte MovingCells;
//             RS485Result ret;
//             if (PInfo.Cell > 100)
//             {
//                 bForwardMoving = false;
//                 MovingCells = (byte)(200 - PInfo.Cell + 1);
//             }
//             else
//             {
//                 bForwardMoving = true;
//                 MovingCells = (byte)(PInfo.Cell - 1);
//             }            
//             if(!OpenSerialPort())
//                 return RS485Result.Close;
//             if (PInfo.Pillar == Pillar && MovingCells>5)
//             {
//                 ret=Moving(bForwardMoving,MovingCells);
//                 if (ret != RS485Result.OK)
//                     return ret;
//             }
//             ret = GetPassportState(out RxBuffer, out Count);
//             if (ret != RS485Result.OK)
//                 return ret;
//             if (PInfo.Pillar == Pillar && MovingCells > 5)
//             {
//                 ret = Moving(!bForwardMoving, MovingCells);
//                 if (ret != RS485Result.OK)
//                     return ret;
//             }
//             CloseSerialPort();
//             return ret;
//         }
        public RS485Result Display(int l, int c, int s)
        {            
            byte[] Tx;
            Tx = new byte[11];
            if (!OpenSerialPort())
                return RS485Result.Close;
            l--;
            c--;
            Tx[0] = (byte)'#';
            Tx[1] = 0x01;//柱子
            Tx[2] = 0x03;
            Tx[3] = 0x04;
            Tx[4] = WFNetLib.BytesOP.Byte2BCD((byte)l);//
            Tx[5] = WFNetLib.BytesOP.Byte2BCD((byte)(c/10));//
            Tx[6] = WFNetLib.BytesOP.Byte2BCD((byte)(c%10));//
            Tx[7] = (byte)s;
            Tx[8] = WFNetLib.Verify.GetVerify_byteSum(Tx, 1, 7);
            Tx[9] = 0x0d;
            Tx[10] = 0x0a;
            COM.Write(Tx, 0, 11);           
            CloseSerialPort();
            return RS485Result.OK;
        }
        public RS485Result PCDisplay(string str)
        {
            if (!OpenSerialPort())
                return RS485Result.Close;
            Encoding gb2312 = Encoding.GetEncoding("gb2312");
            byte[] encodedBytes = gb2312.GetBytes(str);
            COM.Write(encodedBytes,0,encodedBytes.Length);
            CloseSerialPort();
            return RS485Result.OK;
        }
        public RS485Result GetPassportState(out byte[] RxBuffer, out ushort Count)
        {
            Count = 0;
            RxBuffer = null;
            byte[] Tx;
            byte[] RxTemp;
            Tx = new byte[8];
            RxTemp = new byte[500];
            if (!OpenSerialPort())
                return RS485Result.Close;
            Tx[0] = (byte)'#';
            Tx[1] = Pillar;//柱子
            Tx[2] = 0x01;//(byte)command;
            Tx[3] = 0x00;//长度
            Tx[4] = WFNetLib.Verify.GetVerify_byteSum(Tx, 1, 3);
            Tx[5] = 0x0d;
            Tx[6] = 0x0a;
            COM.DiscardInBuffer();
            COM.Write(Tx, 0, 7);            
            int retry = Settings.Default.PassportPortRetryTimes;
            byte Rx;
            bool bHeader = false;
            while (retry != 0)
            {
                try
                {
                    Rx = (byte)COM.ReadByte();
                }
                catch/* (TimeoutException ex)*/
                {
                    WFNetLib.Log.SystemLogData log = new WFNetLib.Log.SystemLogData();
                    log.LogType = LogType.探测相关.ToString();
                    log.LogContent = "架子号为:" + Pillar.ToString() + ",命令为:读取";
                    log.LogRemark = "通信超时";
                    log.InserSQLLog();
                    break;
                }
                if (bHeader)
                {
                    RxTemp[Count] = Rx;
                    Count++;
                    if (RxTemp[0] != (byte)Pillar && Count == 1)//柱子
                    {
                        retry--;
                        bHeader = false;
                        Count = 0;
                        continue;
                    }
                    if (RxTemp[1] != 0x01 && Count == 2)//命令
                    {
                        retry--;
                        bHeader = false;
                        Count = 0;
                        continue;
                    }
                    if (Count > 4)
                    {
                        ushort l = WFNetLib.BytesOP.MakeShort(RxTemp[2], RxTemp[3]);
                        if ((Count - 7) > l)//接收到数据的长度
                        {
                            retry--;
                            bHeader = false;
                            Count = 0;
                        }
                        else if (Rx == 0x0a && RxTemp[Count - 2] == 0x0d)//收到了结尾
                        {
                            if (l == Count - 7)
                            {
                                if (WFNetLib.Verify.GetVerify_byteSum(RxTemp, 4, l) == RxTemp[Count - 3])
                                {
                                    RxBuffer = new byte[Count];
                                    for (int i = 0; i < Count; i++)
                                        RxBuffer[i] = RxTemp[i];
                                    CloseSerialPort();
                                    return RS485Result.OK;
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (Rx == (byte)'#')
                        bHeader = true;
                    else
                        retry--;
                }
            }
            CloseSerialPort();
            return RS485Result.Timeout;
        }
        public RS485Result Moving(Boolean bForwardMoving,byte MovingCells)
        {
            ushort Count=0;
            byte[] Tx;
            byte[] RxTemp;
            Tx = new byte[9];
            RxTemp = new byte[500];
            Boolean bOk = false;
            if (!OpenSerialPort())
                return RS485Result.Close;
            Tx[0] = (byte)'#';
            Tx[1] = Pillar;//柱子
            Tx[2] = 0x02;//旋转
            Tx[3] = 0x02;//长度
            if (bForwardMoving)
                Tx[4] = 0x01;
            else
            {
                Tx[4] = 0x00;
                MovingCells-=2;
            }
            Tx[5] = MovingCells;//柱子
            Tx[6] = WFNetLib.Verify.GetVerify_byteSum(Tx, 1, 5);
            Tx[7] = 0x0d;
            Tx[8] = 0x0a;
            bOk = false;
            while (!bOk)
            {
                COM.DiscardInBuffer();
                COM.Write(Tx, 0, 9);                
                int retry = Settings.Default.PassportPortRetryTimes;
                byte Rx;
                bool bHeader = false;
                while (retry != 0)
                {
                    try
                    {
                        Rx = (byte)COM.ReadByte();
                        Debug.Write(string.Format("{0:X}", Rx));
                    }
                    catch/* (TimeoutException ex)*/
                    {
                        retry = 0;
                        WFNetLib.Log.SystemLogData log = new WFNetLib.Log.SystemLogData();
                        log.LogType = LogType.探测相关.ToString();
                        log.LogContent = "架子号为:" + Pillar.ToString() + ",命令为:旋转";
                        log.LogRemark = "通信超时";
                        log.InserSQLLog();
                        break;
                        //textBox1.AppendText("超时" + "\r\n");
                    }
                    if (bHeader)
                    {
                        RxTemp[Count] = Rx;
                        Count++;
                        if (RxTemp[0] != Pillar && Count == 1)//柱子
                        {
                            retry--;
                            bHeader = false;
                            Count = 0;
                            continue;
                        }
                        if (RxTemp[1] != 0x02 && Count == 2)//命令
                        {
                            retry--;
                            bHeader = false;
                            Count = 0;
                            continue;
                        }
                        if (Count > 4)
                        {
                            ushort l = WFNetLib.BytesOP.MakeShort(RxTemp[2], RxTemp[3]);
                            if ((Count - 7) > l)//接收到数据的长度
                            {
                                retry--;
                                bHeader = false;
                                Count = 0;
                            }
                            else if (RxTemp[Count - 1] == 0x0a && RxTemp[Count - 2] == 0x0d)//收到了结尾
                            {
                                if (l == Count - 7)
                                {
                                    if (WFNetLib.Verify.GetVerify_byteSum(RxTemp, 4, l) == RxTemp[Count - 3])
                                    {
                                        if (RxTemp[4] == 0x01)//成功
                                        {
                                            bOk = true;
                                            break;
                                        }
                                        else
                                        {
                                            retry--;
                                            Thread.Sleep(1000);
                                            bHeader = false;
                                            Count = 0;
                                            WFNetLib.Log.SystemLogData log = new WFNetLib.Log.SystemLogData();
                                            log.LogType = LogType.探测相关.ToString();
                                            log.LogContent = "架子号为:" + Pillar.ToString() + ",命令为:旋转:"+RxTemp[4].ToString("%d");
                                            log.LogRemark = "旋转失败";
                                            log.InserSQLLog();
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        if (Rx == (byte)'#')
                            bHeader = true;
                        else
                            retry--;
                    }
                }
                if (retry == 0)
                {
                    CloseSerialPort();
                    return RS485Result.Timeout;
                }
            }
            CloseSerialPort();
            return RS485Result.OK;
        }
        private Boolean OpenSerialPort()
        {
            if (COM!=null && COM.IsOpen)
            {
                return true;
            }
            COM = new SerialPort(Settings.Default.PassportPortName,
                                 Settings.Default.PassportPortBaudRate,
                                 Parity.None, 8, StopBits.One
                                 );
            COM.ReadTimeout = Settings.Default.PassportPortTimeOut;
            COM.Close();
            while (true)
            {
                try
                {
                    COM.Open();
                    break;
                }
                catch (Exception ex)
                {
                    if (MessageBox.Show(ex.Message, "Waring", MessageBoxButtons.RetryCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                    {
                        WFNetLib.Log.SystemLogData log = new WFNetLib.Log.SystemLogData();
                        log.LogType = LogType.探测相关.ToString();
                        log.LogContent = "与护照通信的串口无法打开:" + Settings.Default.PassportPortName + ",系统提示:" + ex.Message;
                        log.LogRemark = "串口无法打开";
                        log.InserSQLLog();
                        return false;
                    }
                }
            }
            return true;
        }
        private void CloseSerialPort()
        {
            COM.Close();
            COM.Dispose();
        }
    }
}
